/*
 * @Author: 0x9DEFA478
 * @Date: 2021-08-17 23:59:50
 * @LastEditTime: 2022-01-08 22:36:59
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * QQ:2652450237
 * ============================================================================================================================================
 * 
 * 
 * 
 *                                                                                               ************      ****************************
 *                                                                                             ************      ****************************  
 *                                                                                           ************      ****************************    
 *                                                                                         ************      ****************************      
 *                                                                                       ************      ************                        
 *                                                                                     ************      ************                          
 *                                                                                   ************      ************                            
 *                                                                                 ************      ************                              
 *                                                                               ************      ************                                
 *                                                                             ************      ************                                  
 *                                                                           ************      ************                                    
 *                                                                         ************      ************                                      
 *                                                                       ************      ************                                        
 *                                                                     ************      ************                                          
 *                                                                   ************      ************                                            
 *                                                                 ************      ************                                              
 *                                                               ************      ************                                                
 *                                                             ************      ************                                                  
 *                                                           ************      ************                                                    
 *                                                         ************      ************                                                      
 *                                                       ************      ************                                                        
 *                                                     ************      ************                                                          
 *                                                   ************      ************                                                            
 *                                                 ************      ************                                                              
 *                                               ************      ************                                                                
 *                                             ************      ************                                                                  
 *                                           ************      ************                                                                    
 *                                         ************      ************                                                                      
 *                                       ************      ************                                                                        
 *                                     ************      ************                                                                          
 *                                   ************      ************                                                                            
 *                                 ************      ************                                                                              
 *                               ************      ************                                                                                
 *                             ************      ************                                                                                  
 *                           ************      ************                                                                                    
 *                         ************      ************                                                                                      
 *       ****************************      ************                                                                                        
 *     ****************************      ************                                                                                          
 *   ****************************      ************                                                                                            
 * ****************************      ************                                                                                              
 * 
 * 
 * 
 * ============================================================================================================================================
 * 
 */
#include "I_VCOM.h"
#include "H_ThreadScheduler.h"
#include "Peripherals_Instence.h"
#include "MemoryMalloc.h"
#include "H_FIFO.h"
#include "IP_UART.h"
#include "usbd_class_if.h"


#define vI_VCOM_RecvBufferSize 4096
#define vI_VCOM_NumOfRecvPack 128

#define vI_VCOM_TransmitBufferSize 4096
#define vI_VCOM_NumOfTransmitPack 128

#define vI_VCOM_UART_TxBufferSize 512
#define vI_VCOM_UART_RxBufferSize 1024

struct{

  
  H_FIFO* RecvFIFO;
  H_FIFO* TransmitFIFO;
  

  //H_TS_Semaphore* RecvSemaphore;
  H_TS_Semaphore* TransmitDoneSemaphore;
  H_TS_Semaphore* USBINDoneSemaphore;
  //H_TS_Semaphore* USBOUTSemaphore;

  H_TS_Mailbox* USBOUT_Recv;

  unsigned char* USBIN_Buffer;

  void* TxBuffer;
  void* RxBuffer;

  H_TS_MessageQueue* InvokeQueue;

  struct{
    volatile unsigned int BaudRate;
    volatile unsigned int WordLength;
    volatile unsigned int StopBits;
    volatile unsigned int Parity;
  }Param;

  volatile int IsRun;

}I_VCOM;


static void TransmitDoneCallback(void* v){

  H_TS_SemaphoreGive_ISR(I_VCOM.TransmitDoneSemaphore);
}

static void RecvDoneCallback(void* v,void* Buffer,int Size){
  int index;
  if(0==H_FIFO_Write(I_VCOM.RecvFIFO,Buffer,Size)){
    //H_TS_SemaphoreGive_ISR(I_VCOM.RecvSemaphore);

    index=1;
    H_TS_MailboxPost(I_VCOM.USBOUT_Recv,&index);
  }
}

static void Transmit(unsigned char* Data,int Length){

  while(IP_UART_DMATxRx_TransmitIsDone(ip_uart5)!=0){
    //noEdit
  }

  IP_UART_DMATxRx_Transmit(ip_uart5,Data,Length);
  H_TS_SemaphoreTake(I_VCOM.TransmitDoneSemaphore);
} 

static void USBIN(unsigned char* Data,int Length){
  int i;

  i=Length;
  while(i>0){
    i--;
    I_VCOM.USBIN_Buffer[i]=Data[i];
  }

  usbd_class_CDC_Send(I_VCOM.USBIN_Buffer,Length);
  H_TS_SemaphoreTake(I_VCOM.USBINDoneSemaphore);
}





/**
 * @brief 阻塞线程 向串口发送数据
 * @param Data 数据指针
 * @param Length 长度
 * @return 无
 */
static void I_VCOM_Write(unsigned char* Data,int Length){
  int maxPackSize;

  H_TS_LockLock(ip_uart5_Lock);

  if(ip_uart5==NULL){
    H_TS_LockUnlock(ip_uart5_Lock);
    return;
  }

  maxPackSize=IP_UART_DMATxRx_GetMaxTransmitSize(ip_uart5);

  while(Length>maxPackSize){
    Transmit(Data,maxPackSize);
    Data=&Data[maxPackSize];
    Length-=maxPackSize;
  }
  if(Length>0){
    Transmit(Data,Length);
  }

  H_TS_LockUnlock(ip_uart5_Lock);

}

// H_TS_Thread* I_VCOM_txThread_handle;
// static int I_VCOM_txThread(void* v){
//   unsigned char* readData;
//   int readLength;

//   for(;;){
//     H_TS_SemaphoreTake(I_VCOM.USBOUTSemaphore);
//     readData=H_FIFO_Read(I_VCOM.TransmitFIFO,&readLength);
//     if(readData!=NULL){
//       I_VCOM_Write(readData,readLength);
//       H_FIFO_Next(I_VCOM.TransmitFIFO);
//     }
//   }

// }

// H_TS_Thread* I_VCOM_rxThread_handle;
// static int I_VCOM_rxThread(void* v){
//   unsigned char* readData;
//   int readLength;

//   for(;;){
//     H_TS_SemaphoreTake(I_VCOM.RecvSemaphore);
//     readData=H_FIFO_Read(I_VCOM.RecvFIFO,&readLength);
//     if(readData!=NULL){
//       if(usbd_class_IsConnect()!=0){

        
//         while(readLength>512){
//           USBIN(readData,512);
//           readLength-=512;
//           readData=&readData[512];
//         }
//         if(readLength>0){
//           USBIN(readData,readLength);
//         }
//       }
      
//       H_FIFO_Next(I_VCOM.RecvFIFO);
//     }
//   }
// }

H_TS_Thread* I_VCOM_txrxThread_handle;
static int I_VCOM_txrxThread(void* v){
  int index;
  unsigned char* readData;
  int readLength;

  for(;;){
    H_TS_MailboxReceive(I_VCOM.USBOUT_Recv,&index);
    switch(index){
      case 0:
        readData=H_FIFO_Read(I_VCOM.TransmitFIFO,&readLength);
        if(readData!=NULL){
          I_VCOM_Write(readData,readLength);
          H_FIFO_Next(I_VCOM.TransmitFIFO);
        }
        break;
      case 1:
        readData=H_FIFO_Read(I_VCOM.RecvFIFO,&readLength);
        if(readData!=NULL){
          if(usbd_class_IsConnect()!=0){

            
            while(readLength>512){
              USBIN(readData,512);
              readLength-=512;
              readData=&readData[512];
            }
            if(readLength>0){
              USBIN(readData,readLength);
            }
          }
          
          H_FIFO_Next(I_VCOM.RecvFIFO);
        }
        break;
      default:
        break;
    }
  }
}



H_TS_Thread* I_VCOM_Invoke_Thread_handle;
static int I_VCOM_Invoke_Thread(void* v){
  void* v0;
  void* v1;
  void (*Callee)(void*);

  for(;;){
    H_TS_MessageQueueReceive(I_VCOM.InvokeQueue,&v0,&v1);
    Callee=v0;
    Callee(v1);
  }
}

/**
 * @brief I_VCOM的数据传输到主机完成调用
 * @return 无
 */
void I_VCOM_INDone_Callback(){

  H_TS_SemaphoreGive_ISR(I_VCOM.USBINDoneSemaphore);
}

/**
 * @brief 主机数据传入到I_VCOM
 * @param Data 数据指针
 * @param Size 数据大小
 * @return 无
 */
void I_VCOM_DataOut(unsigned char* Data,int Size){
  int index;
  if(0==H_FIFO_Write(I_VCOM.TransmitFIFO,Data,Size)){
    //H_TS_SemaphoreGive_ISR(I_VCOM.USBOUTSemaphore);

    index=0;
    H_TS_MailboxPost(I_VCOM.USBOUT_Recv,&index);
  }
}

/**
 * @brief 获取异步调用队列
 * @return 异步调用队列
 */
void* I_VCOM_GetInvokeQueue(){
  return I_VCOM.InvokeQueue;
}

/**
 * @brief 初始化I_VCOM实例
 * @return 无
 */
void I_VCOM_Init(){
  void* v0;
  void* v1;

  I_VCOM.Param.BaudRate=115200;
  I_VCOM.Param.WordLength=UART_WORDLENGTH_8B;
  I_VCOM.Param.StopBits=UART_STOPBITS_1;
  I_VCOM.Param.Parity=UART_PARITY_NONE;

  I_VCOM.TransmitDoneSemaphore=new_H_TS_Semaphore(4);
  //I_VCOM.RecvSemaphore=new_H_TS_Semaphore(vI_VCOM_NumOfRecvPack);
  I_VCOM.USBINDoneSemaphore=new_H_TS_Semaphore(4);
  //I_VCOM.USBOUTSemaphore=new_H_TS_Semaphore(vI_VCOM_NumOfTransmitPack);

  I_VCOM.USBOUT_Recv=new_H_TS_Mailbox(vI_VCOM_NumOfTransmitPack+vI_VCOM_NumOfRecvPack+2,sizeof(int),2);
  
  I_VCOM.RecvFIFO=MemoryMalloc_DTCM_Malloc(sizeof(H_FIFO));

  if(I_VCOM.RecvFIFO==NULL){
    for(;;){
    }
  }

  v0=MemoryMalloc_SRAM_Malloc(vI_VCOM_RecvBufferSize);
  v1=MemoryMalloc_SRAM_Malloc(vI_VCOM_NumOfRecvPack*sizeof(int));

  if((v0==NULL)||(v1==NULL)){
    for(;;){
    }
  }

  H_FIFO_Init(I_VCOM.RecvFIFO,vH_FIFO_Type_byte,v0,vI_VCOM_RecvBufferSize,v1,vI_VCOM_NumOfRecvPack);



  I_VCOM.TransmitFIFO=MemoryMalloc_DTCM_Malloc(sizeof(H_FIFO));

  if(I_VCOM.TransmitFIFO==NULL){
    for(;;){
    }
  }

  v0=MemoryMalloc_SRAM_Malloc(vI_VCOM_TransmitBufferSize);
  v1=MemoryMalloc_SRAM_Malloc(vI_VCOM_NumOfTransmitPack*sizeof(int));

  if((v0==NULL)||(v1==NULL)){
    for(;;){
    }
  }

  H_FIFO_Init(I_VCOM.TransmitFIFO,vH_FIFO_Type_byte,v0,vI_VCOM_TransmitBufferSize,v1,vI_VCOM_NumOfTransmitPack);


  I_VCOM.USBIN_Buffer=MemoryMalloc_SRAM_Malloc(512);

  I_VCOM.InvokeQueue=new_H_TS_MessageQueue(4);
  if(I_VCOM.InvokeQueue==NULL){
    for(;;){
    }
  }

  //I_VCOM_txThread_handle=H_TS_StartNewThread_LowPriority(I_VCOM_txThread,NULL,512,1024,0);
  //I_VCOM_rxThread_handle=H_TS_StartNewThread_LowPriority(I_VCOM_rxThread,NULL,512,1024,0);
  I_VCOM_txrxThread_handle=H_TS_StartNewThread_LowPriority(I_VCOM_txrxThread,NULL,512,1024,0);
  I_VCOM_Invoke_Thread_handle=H_TS_StartNewThread_LowPriority(I_VCOM_Invoke_Thread,NULL,512,1024,0);

  I_VCOM.IsRun=-1;

}


/**
 * @brief I_VCOM关闭
 * @return 无
 */
void I_VCOM_Disable(){

  H_TS_LockLock(ip_uart5_Lock);

  if(I_VCOM.IsRun==0){
    H_TS_LockUnlock(ip_uart5_Lock);
    return;
  }
  I_VCOM.IsRun=0;


  MX_UART5_DeInit();

  MemoryMalloc_SRAM_Free(I_VCOM.TxBuffer);
  MemoryMalloc_SRAM_Free(I_VCOM.RxBuffer);

  H_TS_LockUnlock(ip_uart5_Lock);
}

/**
 * @brief I_VCOM使能
 * @return 无
 */
void I_VCOM_Enable(){

  H_TS_LockLock(ip_uart5_Lock);

  if(I_VCOM.IsRun!=0){
    H_TS_LockUnlock(ip_uart5_Lock);
    return;
  }
  I_VCOM.IsRun=-1;

  MX_UART5_Init(I_VCOM.Param.BaudRate,I_VCOM.Param.WordLength,I_VCOM.Param.StopBits,I_VCOM.Param.Parity);

  IP_UART_DMATxRx_SetCallback(ip_uart5,NULL,TransmitDoneCallback,RecvDoneCallback);
  I_VCOM.TxBuffer=MemoryMalloc_SRAM_Malloc(vI_VCOM_UART_TxBufferSize);
  I_VCOM.RxBuffer=MemoryMalloc_SRAM_Malloc(vI_VCOM_UART_RxBufferSize);
  if((I_VCOM.TxBuffer==NULL)||(I_VCOM.RxBuffer==NULL)){
    for(;;){
    }
  }
  IP_UART_DMATxRx_Start(ip_uart5,I_VCOM.TxBuffer,vI_VCOM_UART_TxBufferSize,I_VCOM.RxBuffer,vI_VCOM_UART_RxBufferSize);

  H_TS_LockUnlock(ip_uart5_Lock);
}

/**
 * @brief 设置I_VCOM参数
 * @param BaudRate 波特率
 * @param WordLength 位宽
 * @param StopBits 停止位
 * @param Parity 校验位
 * @return 无
 */
void I_VCOM_SetParam(unsigned int BaudRate,unsigned int WordLength,unsigned int StopBits,unsigned int Parity){
  
  H_TS_LockLock(ip_uart5_Lock);

  I_VCOM.Param.BaudRate=BaudRate;
  I_VCOM.Param.WordLength=WordLength;
  I_VCOM.Param.StopBits=StopBits;
  I_VCOM.Param.Parity=Parity;

  if(I_VCOM.IsRun!=0){
    I_VCOM_Disable();
    I_VCOM_Enable();
  }

  H_TS_LockUnlock(ip_uart5_Lock);
}

